<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Generate and Encrypt Symmetric Key</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
        }
        input, button {
            margin: 10px 0;
            padding: 10px;
            width: 300px;
        }
        button {
            background-color: #4CAF50;
            color: white;
            border: none;
            cursor: pointer;
        }
        button:hover {
            background-color: #45a049;
        }
        .output {
            margin-top: 20px;
            padding: 10px;
            border: 1px solid #ccc;
            max-height: 200px;
            overflow-y: auto;
        }
    </style>
</head>
<body>
<h1>Generate and Encrypt Symmetric Key</h1>
<input type="text" id="userIdInput" placeholder="Enter User ID" />
<button onclick="generateAndEncryptKey()">Generate and Send Encrypted Key</button>
<div class="output" id="output"></div>

<script>
    // Base64 解码函数
    function base64ToArrayBuffer(base64) {
        const binaryString = window.atob(base64);
        const len = binaryString.length;
        const bytes = new Uint8Array(len);
        for (let i = 0; i < len; i++) {
            bytes[i] = binaryString.charCodeAt(i);
        }
        return bytes.buffer;
    }

    // 将 PEM 格式公钥转换为 ArrayBuffer
    function pemToBinary(pem) {
        const base64 = pem.replace(/-----BEGIN PUBLIC KEY-----/, '')
            .replace(/-----END PUBLIC KEY-----/, '')
            .replace(/\s+/g, '');
        return base64ToArrayBuffer(base64);
    }

    // 主逻辑
    async function generateAndEncryptKey() {
        const outputDiv = document.getElementById('output');
        outputDiv.innerHTML = ''; // 清空输出

        try {
            const userId = document.getElementById('userIdInput').value.trim();
            if (!userId) {
                throw new Error("Please enter a valid User ID.");
            }

            // 1. 发送 HTTP 请求获取公钥
            const response = await fetch('http://localhost:8089/user/public');
            if (!response.ok) {
                throw new Error(`HTTP error! Status: ${response.status}`);
            }

            const result = await response.json();
            if (result.code !== 200) {
                throw new Error(`Server error: ${result.msg}`);
            }

            const publicKeyPEM = result.data;

            outputDiv.innerHTML += `<p>Fetched Public Key: ${publicKeyPEM}</p>`;

            // 2. 加载公钥
            const publicKeyDer = pemToBinary(publicKeyPEM);

            const publicKey = await window.crypto.subtle.importKey(
                "spki", // 导入 SPKI 格式的公钥
                publicKeyDer,
                {
                    name: "RSA-OAEP",
                    hash: "SHA-256", // 使用 SHA-256 哈希算法
                },
                true, // 是否可导出
                ["encrypt"] // 允许的操作
            );

            outputDiv.innerHTML += `<p>Loaded Public Key successfully.</p>`;

            // 3. 生成对称密钥 (AES)
            const symmetricKey = await window.crypto.subtle.generateKey(
                {
                    name: "AES-GCM",
                    length: 256, // 256 位密钥长度
                },
                true, // 是否可导出
                ["encrypt", "decrypt"] // 允许的操作
            );

            outputDiv.innerHTML += `<p>Generated Symmetric Key successfully.</p>`;

            // 4. 导出对称密钥为原始字节格式
            const rawSymmetricKey = await window.crypto.subtle.exportKey("raw", symmetricKey);

            outputDiv.innerHTML += `<p>Raw Symmetric Key: ${Array.from(new Uint8Array(rawSymmetricKey)).join(', ')}</p>`;

            // 5. 使用公钥加密对称密钥
            const encryptedSymmetricKey = await window.crypto.subtle.encrypt(
                {
                    name: "RSA-OAEP",
                },
                publicKey,
                rawSymmetricKey
            );

            // 将加密后的数据转换为 Base64 字符串
            const encryptedKeyBase64 = btoa(String.fromCharCode(...new Uint8Array(encryptedSymmetricKey)));

            outputDiv.innerHTML += `<p>Encrypted Symmetric Key: ${encryptedKeyBase64}</p>`;

            // 6. 调用后端接口发送加密后的对称密钥
            const sendResponse = await fetch(`http://localhost:8089/user/public?symmetricKey=${encodeURIComponent(encryptedKeyBase64)}`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
            });

            if (!sendResponse.ok) {
                throw new Error(`Failed to send encrypted key. Status: ${sendResponse.status}`);
            }

            const sendResult = await sendResponse.json();
            if (sendResult.code !== 200) {
                throw new Error(`Server error: ${sendResult.msg}`);
            }

            outputDiv.innerHTML += `<p>Encrypted Key sent successfully!</p>`;
        } catch (error) {
            outputDiv.innerHTML += `<p style="color: red;">Error: ${error.message}</p>`;
        }
    }
</script>
</body>
</html>